package securityproject;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import securityproject.utils.Constants;
import securityproject.utils.LogUtils;
import securityproject.utils.RuleUtils;

public class XSLRuleApplier extends HttpServlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = 7775723838849235095L;
	
	public static final String FILENAME = "filename";

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {

		try {

			String filename = (String) req.getParameter("filename");

			if (filename == null) {
				throw new IllegalArgumentException("No filename");
			}

			// Use the DocumentBuilderFactory to provide access to a
			// DocumentBuilder.
			File tmpFile = new File(Constants.TEMP_FOLDER + filename);

			if (!tmpFile.exists()) {

				// NO need to activate this since pdml converter automatically
				// activate
				// prefix rule after creating pdml, and so pdml files that are
				// located
				// in log folder have already been changed by the prefix rule.

				// //activating prefix rules
				// ruleFilter(Constants.LOG_FOLDER + filename,
				// Constants.TEMP_FOLDER + filename,
				// Constants.XSL_PREFIX_RULES_FILE);

				// TODO delete this when we know pdml converter works 100
				// percent
				// File originalFile = new File(Constants.LOG_FOLDER +
				// filename);
				// if (tmpFile.length() != originalFile.length())
				// copy(tmpFile, originalFile);

				copy((new File(Constants.LOG_FOLDER + filename)), (new File(
						Constants.TEMP_FOLDER + filename)));

				// activating filter rules

				File globalActiveRulesFolder = new File(RuleUtils
						.getRuleFolder(RuleUtils.GLOBAL, true));

				for (File xslRule : globalActiveRulesFolder.listFiles()) {
					if (xslRule.getName().contains("exclude")) {
						ruleFilter(Constants.TEMP_FOLDER + filename,
								Constants.TEMP_FOLDER + filename, xslRule
										.getPath());
					}
				}
				String fileRulesFolder = LogUtils.getLogName(filename);
				File xslSpecificFolderRules = new File(RuleUtils
						.getRuleFolder(fileRulesFolder, true));

				for (File xslSpecificFileRule : xslSpecificFolderRules
						.listFiles()) {
					ruleFilter(Constants.TEMP_FOLDER + filename,
							Constants.TEMP_FOLDER + filename, RuleUtils
									.getRuleFolder(fileRulesFolder, true)
									+ xslSpecificFileRule.getName());
				}
				for (File xslRule : globalActiveRulesFolder.listFiles()) {
					if (!xslRule.getName().contains("exclude")) {
						ruleFilter(Constants.TEMP_FOLDER + filename,
								Constants.TEMP_FOLDER + filename,
								RuleUtils.getRuleFolder(
										RuleUtils.GLOBAL, true)
										+ xslRule.getName());
					}
				}

			}
			// else {
			//
			// File xslRulesFolder = new File(
			// Constants.XSL_ACTIVE_FILTER_RULES_FOLDER);
			// // Saving the original last modified time of tmpFile because we
			// // may modify it in the next loop. So we need the original for
			// // comparing if the rule is newer then the original file.
			// long curFileLadtModifiedTime = tmpFile.lastModified();
			// for (File xslRule : xslRulesFolder.listFiles()) {
			// if (xslRule.lastModified() > curFileLadtModifiedTime) {
			// ruleFilter(Constants.TEMP_FOLDER + filename,
			// Constants.TEMP_FOLDER + filename,
			// Constants.XSL_ACTIVE_FILTER_RULES_FOLDER
			// + xslRule.getName());
			// }
			// }

			// }

			DocumentBuilder dBuilder;
			// Instantiate a DocumentBuilderFactory.
			javax.xml.parsers.DocumentBuilderFactory dfactory = javax.xml.parsers.DocumentBuilderFactory
					.newInstance();
			dBuilder = dfactory.newDocumentBuilder();

			TransformerFactory tFactory = TransformerFactory.newInstance();

			Document inDoc2 = dBuilder.parse(Constants.TEMP_FOLDER + filename);

			// activating suffix rules
			Transformer transformer2 = tFactory
					.newTransformer(new StreamSource(Constants
							.getXSLSuffixRuleFile()));

			transformer2.transform(new DOMSource(inDoc2), new StreamResult(resp
					.getOutputStream()));

		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (TransformerConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (TransformerException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * @param filename
	 * @param dfactory
	 * @throws ParserConfigurationException
	 * @throws TransformerFactoryConfigurationError
	 * @throws SAXException
	 * @throws IOException
	 * @throws TransformerConfigurationException
	 * @throws TransformerException
	 * @throws FileNotFoundException
	 */
	private void ruleFilter(String fromFilename, String toFilename,
			String ruleFileName) throws ParserConfigurationException,
			TransformerFactoryConfigurationError, SAXException, IOException,
			TransformerConfigurationException, TransformerException,
			FileNotFoundException {
		DocumentBuilder dBuilder;
		// Instantiate a DocumentBuilderFactory.
		javax.xml.parsers.DocumentBuilderFactory dfactory = javax.xml.parsers.DocumentBuilderFactory
				.newInstance();
		dBuilder = dfactory.newDocumentBuilder();

		TransformerFactory tFactory = TransformerFactory.newInstance();
		// Use the DocumentBuilder to parse the XML input.
		Document inDoc = dBuilder.parse(fromFilename);

		// Generate a Transformer.
		Transformer transformer = tFactory.newTransformer(new StreamSource(
				ruleFileName));

		FileOutputStream fileOut = new FileOutputStream(toFilename);
		transformer.transform(new DOMSource(inDoc), new StreamResult(fileOut));

		fileOut.flush();
		fileOut.close();
	}

	// TODO delete this when we know pdml converter works 100 percent
	/** Fast & simple file copy. */
	public static void copy(File source, File dest) throws IOException {
		FileChannel in = null, out = null;
		try {
			in = new FileInputStream(source).getChannel();
			out = new FileOutputStream(dest).getChannel();

			long size = in.size();
			MappedByteBuffer buf = in.map(FileChannel.MapMode.READ_ONLY, 0,
					size);

			out.write(buf);

		} finally {
			if (in != null)
				in.close();
			if (out != null)
				out.close();
		}
	}

}
